package cn.bo.cloud.common.core.utils.file;

import cn.bo.cloud.common.core.utils.ExceptionUtils;
import cn.bo.cloud.common.core.utils.HexUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 文件类型工具类
 *
 * @author zhoujumbo
 */
public class FileTypeUtils{
    private final static Logger logger = LoggerFactory.getLogger(FileTypeUtils.class);
    // 默认判断文件头字节内容长度
    private static int default_check_length = 15;
    public final static HashMap<String, String> fileTypeMap = new HashMap<>();



    /**
     * 获取文件类型
     * <p>
     * 例如: zzz.txt, 返回: txt
     * 
     * @param file 文件名
     * @return 后缀（不含".")
     */
    public static String getFileType(File file)
    {
        if (null == file)
        {
            return StringUtils.EMPTY;
        }
        return getFileType(file.getName());
    }

    /**
     * 获取文件类型
     * <p>
     * 例如: zzz.txt, 返回: txt
     *
     * @param fileName 文件名
     * @return 后缀（不含".")
     */
    public static String getFileType(String fileName)
    {
        int separatorIndex = fileName.lastIndexOf(".");
        if (separatorIndex < 0)
        {
            return "";
        }
        return fileName.substring(separatorIndex + 1).toLowerCase();
    }

    /**
     * 获取文件类型
     * 
     * @param photoByte 文件字节码
     * @return 后缀（不含".")
     */
    public static String getFileExtendName(byte[] photoByte)
    {
        String strFileExtendName = "JPG";
        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
        {
            strFileExtendName = "GIF";
        }
        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
        {
            strFileExtendName = "JPG";
        }
        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
        {
            strFileExtendName = "BMP";
        }
        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
        {
            strFileExtendName = "PNG";
        }
        return strFileExtendName;
    }


    /**
     * @param inputStream
     * @return String
     * @description 通过文件头魔数获取文件类型
     * @author xyz
     */
    public static String getFileTypeByMagicNumber(InputStream inputStream) throws Exception {
        byte[] bytes = new byte[default_check_length];
        try {
            // 获取文件头前三位魔数的二进制
            inputStream.read(bytes, 0, bytes.length);
            // 文件头前三位魔数二进制转为16进制, toLowerCase=false默认转换为大写格式
            String code = HexUtil.encodeHexStr(bytes, false);
            for (Map.Entry<String, String> item : fileTypeMap.entrySet()) {
                String fileTypeHexValue = item.getKey();
                if (code.startsWith(fileTypeHexValue)) {
                    return item.getValue();
                }
            }
        } catch (IOException e) {
            throw new Exception("获取文件类型异常：",e);
        }
        return "";
    }

    /**
     * 获取图片文件实际类型,若不是图片则返回
     * @param f
     * @return fileType
     * @author:[shixing_11@sina.com]
     */
    public final static String getImageFileType(File f) {
        if (isImage(f)) {
            try {
                ImageInputStream iis = ImageIO.createImageInputStream(f);
                Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
                if (!iter.hasNext()) {
                    return null;
                }
                ImageReader reader = iter.next();
                iis.close();
                return reader.getFormatName();
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    /**
     * @description 判断文件是否为图片
     * @param file
     * @return true 是 | false 否
     */
    public static final boolean isImage(File file){
        boolean flag = false;
        try {
            BufferedImage bufreader = ImageIO.read(file);
            int width = bufreader.getWidth();
            int height = bufreader.getHeight();
            if(width==0 || height==0){
                flag = false;
            }else {
                flag = true;
            }
        } catch (Exception e) {
            logger.error(ExceptionUtils.getExceptionMessage(e));
            flag = false;
        }
        return flag;
    }

    // 初始化文件头类型，不够的自行补充
    static {
        // 图片类型
        fileTypeMap.put("FFD8FF", "jpg");
        fileTypeMap.put("89504E", "png");
        fileTypeMap.put("47494638", "gif");
        fileTypeMap.put("492049", "tif"); // TIF TIFF
        fileTypeMap.put("49492A", "tif"); // TIF TIFF
        fileTypeMap.put("49492A00", "tif"); // TIF TIFF
        fileTypeMap.put("4D4D002A", "tif"); // TIF TIFF
        fileTypeMap.put("4D4D2A", "tif"); // TIF TIFF
        fileTypeMap.put("4D4D002B", "tif"); // TIF TIFF
        fileTypeMap.put("424D", "bmp");
        fileTypeMap.put("0000010000", "ico");
        fileTypeMap.put("0000010001002020", "ico");
//        fileTypeMap.put("", "swg");
        // 视频类型
        fileTypeMap.put("524946", "wav");
        fileTypeMap.put("57415645", "wav");
        fileTypeMap.put("41564920", "avi");
        fileTypeMap.put("2E7261FD", "ram");
        fileTypeMap.put("2E524D46", "rm");
        fileTypeMap.put("2E524D46", "rmvb");
        fileTypeMap.put("000001BA", "mpg");
        fileTypeMap.put("000001B3", "mpg");
        fileTypeMap.put("6D6F6F76", "mov");
        fileTypeMap.put("4D546864", "mid");
        fileTypeMap.put("464C5601", "flv");
        fileTypeMap.put("000000186674797033677035", "mp4");
        fileTypeMap.put("494433", "mp3");
        fileTypeMap.put("FFFB50", "mp3");
        fileTypeMap.put("3026B2", "wmv");

        // 文档类型
        fileTypeMap.put("0D444F43", "doc"); // DeskMate Document file
        fileTypeMap.put("1234567890FF", "doc"); // MS Word 6.0
        fileTypeMap.put("31BE000000AB0000", "doc"); // MS Word for DOS 6.0
        fileTypeMap.put("7FFE340A", "doc"); // MS Word
        fileTypeMap.put("D0CF11E0A1B11AE1", "doc;dot;xls;xlt;xla;ppt;apr;ppa;pps;pot;msi;sdw;db");
        fileTypeMap.put("D0CF11E0", "dot;ppt;xla;ppa;pps;pot;msi;sdw;db");
//        fileTypeMap.put("", "docx");
        fileTypeMap.put("D0CF11", "ppt");
        fileTypeMap.put("006E1EF0", "ppt"); // PowerPoint presentation subheader (MS Office)
        fileTypeMap.put("0F00E803", "ppt"); // PowerPoint presentation subheader (MS Office)
//        fileTypeMap.put("", "pptx");
        fileTypeMap.put("0902060000001000B9045C00", "xls"); // MS Excel v2
        fileTypeMap.put("0904060000001000F6055C00", "xls"); // MS Excel v4
        fileTypeMap.put("D0CF11", "xls");
        fileTypeMap.put("D0CF11E0", "xls"); // MS Excel
        fileTypeMap.put("0908100000060500", "xls"); // Excel spreadsheet subheader (MS Office)
//        fileTypeMap.put("", "xlsx");
//        fileTypeMap.put("", "mmp");
//        fileTypeMap.put("", "xlt");

//        fileTypeMap.put("", "et");
//        fileTypeMap.put("", "ett");

//        fileTypeMap.put("", "pps");
//        fileTypeMap.put("", "pot");
//        fileTypeMap.put("", "dpt");
//        fileTypeMap.put("", "dps");
//        fileTypeMap.put("", "wpt");
//        fileTypeMap.put("", "wps");
//        fileTypeMap.put("", "dot");
        fileTypeMap.put("AC9EBD8F", "qdf");
        fileTypeMap.put("FF575043", "wpd");

//        fileTypeMap.put("", "vsdx");
//        fileTypeMap.put("494e5345525420494e54", "sql");
        fileTypeMap.put("000100005374616E64617264204A6574204442", "mdb");
        fileTypeMap.put("5374616E64617264204A", "mdb");

        fileTypeMap.put("25504446", "pdf");

        // 压缩包类型
        fileTypeMap.put("504B0304", "zip");
        fileTypeMap.put("504B3030", "zip");
        fileTypeMap.put("52617221", "rar");
        fileTypeMap.put("377ABCAF271C", "7z");
        fileTypeMap.put("1F8B", "gz");


        // 文本类型
        fileTypeMap.put("3C21444F4354", "html,htm");
        fileTypeMap.put("3C48544D4C3E", "html,htm");
        fileTypeMap.put("3C68746D6C3E", "html,htm");
        fileTypeMap.put("68746D6C3E", "html,htm");
//        fileTypeMap.put("48544d4c207b0d0a0942", "css");
//        fileTypeMap.put("696b2e71623d696b2e71", "js");
        fileTypeMap.put("46726f6d3a203d3f6762", "eml");
        fileTypeMap.put("CFAD12FE", "dbx"); // Outlook
        fileTypeMap.put("CFAD12FEC5FD746F", "dbx"); //Outlook Express
        fileTypeMap.put("2142444E", "pst"); //Microsoft Outlook Personal Folder file
        fileTypeMap.put("3C3F78", "xml");
        fileTypeMap.put("3C3F786D6C", "xml");
        fileTypeMap.put("FFFE3C0052004F004F0054005300540055004200", "xml");
//        fileTypeMap.put("3c25402070616765206c", "jsp");

        // 其他类型
//        fileTypeMap.put("41433130313500000000", "dwg");
//        fileTypeMap.put("7b5c727466315c616e73", "rtf");
        fileTypeMap.put("4d5a9000030000000400", "exe");
//        fileTypeMap.put("504b03040a0000000000", "jar");
//        fileTypeMap.put("235468697320636f6e66", "ini");
//        fileTypeMap.put("38425053000100000000", "psd");
//        fileTypeMap.put("252150532D41646F6265", "ps");

    }
}